package logica.estructura;

import resources.NTree.*;
import logica.analizador.DocumentoJerarquico;

import java.util.Vector;

import excepciones.ContenidoException;
import excepciones.DataStructureException;

public class NTreeDocumento extends NTree{
	
	private static String root = "root"; 

	public NTreeDocumento(Object aText) {
		//super(root);
		//this.addElement(aText);
		super(aText);
		//this.createTreeFromRoot(this, new DocumentoJerarquico(texto.getContenido()));
	}

	public NTreeDocumento()
	{
		super();
	}
	
	public void addElement(Object aValue) {
		this.childs().addElement(new NTreeDocumento(aValue));
	}
	
	public void addTo(Object aObject, Object aValue) 
	{
		if (this.value().equals(aObject))
		{
			if (aValue instanceof NTreeDocumento || aValue instanceof NTree)
			{
				this.addNTree(aValue);
			}
			else
			{
				this.addElement(aValue);
			}
		}
		else
		{
			for (int index = 0; index < this.childs().size(); index++)
			{
				((NTreeDocumento) this.childs().elementAt(index)).addTo(aObject, aValue);
			}
		}
	}
	
	public NTreeDocumento createTreeFromRoot(NTreeDocumento arbol, DocumentoJerarquico texto) throws ContenidoException, DataStructureException
	{
		if (texto.tieneSecciones(texto.getContenido()) == 0)
		{
			arbol.addNTree(new NTreeDocumento(texto.getContenido()));
		}
		else
		{
			Vector<String> secciones = texto.getContenidoSecciones();
			
			for(int i=0; i<secciones.size(); i++)
			{
				DocumentoJerarquico nuevaSeccion = new DocumentoJerarquico(secciones.get(i));
				arbol.addNTree(arbol.createTreeFromRoot(new NTreeDocumento(nuevaSeccion.getTitulo()), nuevaSeccion)); 
			}
		}
		return arbol;
	}
	
	/**
	 * Esta funcion renderiza el texto contenido en el arbol a formato:
	 * Wiki o Numerado
	 * 
	 * @param arbol Arbol a renderizar.
	 * @param opcion String con la opcion a renderizar.
	 * @param nivel este es un entero que indica en que nivel estamos, al incio es nivel 0, la raiz.
	 * @param indice este indice nos sirve para cuando es numerado, seria el numero de seccion.
	 * */
	
	public String renderizar(boolean opcion, int nivel, int indice)
	{
		StringBuffer resultado = new StringBuffer();
		String identificador="";
		
		if (opcion)
		{
			identificador="=";
			for(int i=0; i<nivel; i++)
			{
				identificador=identificador+"=";
			}
		}
		else
		{
			identificador="1.";
			for(int i=0; i<nivel; i++)
			{   
				identificador=identificador+((Integer)(indice)).toString()+".";
			}
		}
		
		resultado.append(identificador).append(" ").append(((String)this.value()).trim()).append("\n");

		if (this.childs().size()>0)
		{
			nivel++;
		}
		
		for (int index = 0; index < this.childs().size(); index++)
		{
			resultado.append(((NTreeDocumento)(this.childs().elementAt(index))).renderizar(opcion, nivel, indice+index));
		}
			
		return resultado.toString();
	}
	
	public NTreeDocumento fusionarArboles(NTreeDocumento unArbol)
	{
		NTreeDocumento aResultado=new NTreeDocumento(NTreeDocumento.root);
		fusionarArbolesTmp(this, unArbol, unArbol, NTreeDocumento.root, aResultado);
		return  aResultado;
	}
	
	public void fusionarArbolesTmp (NTreeDocumento arbolIzq, NTreeDocumento arbolDer, NTreeDocumento unArbol, Object padre, NTreeDocumento aResultado)
	{
		Fusion elemento=null;
		Fusion elemento2=null;
		
		//Suponemos ambos elementos iguales.
		elemento = new Fusion(this.value().toString());
		
		//Comparamos con el otro elemento.
		if (!this.value().equals(unArbol.value()))
		{
			elemento2 = new Fusion(unArbol.value().toString());
			//El elemento this.value() esta contenido en el arbol derecho
			if (arbolDer.contains(this.value()))
			{	//El valor aparece en otra seccion del arbol, movido. Lo pintamos de Azul (1).
				elemento.setColor(1);
			}
			else
			{	//El valor no aparece en otra seccion del arbol, ausente. Lo pintamos de Rojo (2).
				elemento.setColor(2);
			}
			if (arbolIzq.contains(this.value()))
			{	//El valor aparece en otra seccion del arbol, movido. Lo pintamos de Azul (1).
				elemento2.setColor(1);
			}
			else
			{	//El valor no aparece en otra seccion del arbol, ausente. Lo pintamos de Rojo (2).
				elemento2.setColor(2);
			}
		}
		//Agregamos al arbol resultado
		aResultado.addTo(padre, elemento);

		//En caso de que sean diferentes.
		if (elemento2!=null)
		{
			aResultado.addTo(padre, elemento2);
		}

		
		//Si ambos no tiene descendientes.
		if (this.childs().isEmpty() && unArbol.childs().isEmpty())
		{
			return;
		}
		else if (this.childs().isEmpty())
		{
			for(int i=0; i<unArbol.childs().size(); i++)
			{
				aResultado.addTo(elemento2, (NTreeDocumento)((Vector)unArbol.childs()).elementAt(i));
			}
		}
		else if (unArbol.childs().isEmpty())
		{
			for(int i=0; i<this.childs().size(); i++)
			{
				aResultado.addTo(elemento, (NTreeDocumento)((Vector)this.childs()).elementAt(i));
			}
		}
		else if(elemento2!=null)
		{
			for(int i=0; i<this.childs().size(); i++)
			{
				aResultado.addTo(elemento, (NTreeDocumento)((Vector)this.childs()).elementAt(i));
			}
			for(int i=0; i<unArbol.childs().size(); i++)
			{
				aResultado.addTo(elemento2, (NTreeDocumento)((Vector)unArbol.childs()).elementAt(i));
			}
		}
		else
		{
			//NTreeDocumento arbol;
			Vector<NTreeDocumento> thisChilds = this.childs();
			Vector unArbolChilds = unArbol.childs();
			int i;
			for(i=0; i<thisChilds.size(); i++)
			{
				NTreeDocumento iChildThis = (NTreeDocumento)thisChilds.elementAt(i);
				NTreeDocumento iChildUnArbol = null;

				//Codigo por las dudas, para que no explote todo. Segun "Renzo"... :P
				if (i < unArbolChilds.size())
				{
					iChildUnArbol = (NTreeDocumento)unArbolChilds.elementAt(i);	
				}
				if (iChildUnArbol!=null)
				{
					iChildThis.fusionarArbolesTmp(arbolIzq, arbolDer, iChildUnArbol, elemento, aResultado);
					
				}
				else
				{
					aResultado.addTo(elemento, (NTreeDocumento)iChildThis);
				}
			}
			if (unArbolChilds.size()>i)
			{	
				for(int j=i; j<unArbolChilds.size(); j++)
				{
					NTreeDocumento iChildUnArbol = null;
					iChildUnArbol = (NTreeDocumento)unArbolChilds.elementAt(j);
					aResultado.addTo(unArbol.value(), (NTreeDocumento)iChildUnArbol);
				}
			}		
		}

	}		
		

	
}
